package com.twq.types.typeximplicit

/**
 * Created by tangweiqun on 2017/11/20.
 */
class ImplicitBounds[T] {

}

//隐式类型约束
object ImplicitBounds {
  def main(args: Array[String]): Unit = {
    //1、视图边界(View bounds)。
    // 当调用含有视图界定的函数时候，
    // 需要可以通过隐式查找能查找到一个隐式转换来转换一个类型为另一个类型，即Int -> ImplicitBounds[Int]
    implicit def int2ImplicitBounds(i: Int) = new ImplicitBounds[Int]

    foo(2)

    //2、上下文边界(Context bounds)。
    // 当调用含有上下文界定的函数时候，需要可以通过隐式查找能查找到一个可用的隐式值ImplicitBounds[A]
    implicit val implicitBoundsWithInt = new ImplicitBounds[Int]
    bar(3)

    //3、使用场景
    //当你的方法不需要通过名字访问捕获的类型，但又需要在作用域里存在可用的隐式转换的场景
    implicit val intSer = new Serialization[Int] {
      override def ser(t: Int): Array[Byte] = {
        println("ser int " + t)
        Array(t.toByte)
      }
    }
    val receivers = Seq(new Receiver[Int])
    sendMsgToEach(receivers, 3)
  }

  def foo[A <% ImplicitBounds[A]](x: A) = x

  def foo1[A](x: A)(implicit $ev0: A => ImplicitBounds[A]) = x

  def bar[A: ImplicitBounds](x: A) = x

  def bar1[A](x: A)(implicit $ev0: ImplicitBounds[A]) = x


  def sendMsgToEach[A: Serialization](receivers: Seq[Receiver[A]],
                                      a: A) = {
    receivers foreach (_.send(a))
  }
}

class Receiver[T] {
  def send(msg: T)(implicit ser: Serialization[T]) = {
    val bytes = ser.ser(msg)
    println("send msg byte: " + bytes)
  }
}

trait Serialization[T] {
  def ser(t: T): Array[Byte]
}

